#include "main.h"
#include "myMath.h"


void KeyboardCallBackCamera1(unsigned char key, int A, int B);
void KeyboardCallBackCamera2(unsigned char key, int A, int B);
void KeyboardCallBackCamera3(unsigned char key, int A, int B);



int cameraType=1;
float demoAngle=-45;
int demoType=0;
float timeStep=0.5;

float cameraY=7.399995;
//initilizing sun(light source) position 
GLfloat position[] = { 0.0, 10.0, 0.0, 0.0 };

GLfloat no_ambient[]={0.2, 0.2, 0.2, 1.0}; //default ambient
GLfloat lightAmbient[] = {0.7,0.7,0.7,1.0}; //increse luminosity of the scene


void init(void)
{	
  //blend colours across the surface of the polygons
  //another mode to try is GL_FLAT which is flat shading
  glShadeModel(GL_SMOOTH);
  //turn lighting off
  glDisable(GL_LIGHTING);
  //enable OpenGL hidden surface removal
  glDepthFunc(GL_LEQUAL);
  glEnable(GL_DEPTH_TEST);

//initSkyBox();
//PlaySound("sounds/Ball_Rolling.wav",NULL,SND_FILENAME|SND_LOOP|SND_ASYNC);
 }

void reshape(int w, int h)
{
// Sets the viewport
glViewport (0, 0, (GLsizei) w, (GLsizei) h);
// Applies matrix operations to the projection matrix stack
glMatrixMode(GL_PROJECTION);
// Replaces the current matrix with the identity matrix
glLoadIdentity();
// Sets up a perspective projection matrix
gluPerspective(40.0, (GLfloat) w/(GLfloat) h, 0.5, 200.0);
// Applies matrix operations to the modelview matrix stack
glMatrixMode(GL_MODELVIEW);
// Replaces the current matrix with the identity matrix
glLoadIdentity();
}


void renderScene() 
{
    glutMainLoop();
}

void setCamera()
{
switch(cameraType)
	{
	case 1: 
		setCamera1();
		glutKeyboardFunc(KeyboardCallBackCamera1);
		break;
	case 2:
		setCamera2();
		glutKeyboardFunc(KeyboardCallBackCamera2);
		break;
	case 3:
		setCamera3();
		glutKeyboardFunc(KeyboardCallBackCamera3);
		break;
	default:
		break;
	}
}

void draw() 
{
    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); //clear buffer bits

	glLoadIdentity();
	setCamera();
	drawGrid();
	

	switch(demoType)
	{
	case 0:
		demoIntro();
		break;
	case 1:
		demoRotation(demoAngle);
		break;
	case 2:
		demoDotProduct1();
		break;
	case 3:
		demoDotProduct2();
		break;
	case 4:
		demoCrossProduct();
		break;
	case 5:
		demoSubtract();
		break;
	case 6:
		demoLerp(timeStep);
		break;
	};
	//	
	//TVector v=TVector(1.4,-1.3,0.8);
	//TPlane plane=TPlane(TPoint(-2,0,-2),TPoint(2,0,2),TPoint(-2,0,2));
	//TPoint point=TPoint(2,3,2);
	//float away=plane.distanceToPoint(point);
	//char dist[32];
	//sprintf_s(dist,"%f",away);
	//text xyz(-2,3,0,dist,1); //text variable to print the coordinates 
	//xyz.print();

	//m.getOpenGlMatrix();

	//drawVector(v);


	glutSwapBuffers();
}


void idle()
{
	// place to animate stuff

}

//Keyboard controls with Camera1 Enabled
void KeyboardCallBackCamera1(unsigned char key, int A, int B)
{

switch(key)
{
//Camera 1
case '#':
	cameraType=cameraType%3+1;
	break;
// Escapes from the program by pressing 'Esc'
case 27: 
	exit(0); // Terminates the program
	break;
case '+':
	demoAngle+=5;
	if(timeStep<1)timeStep+=0.05;
	break;
case '-':
	demoAngle-=5;
	if(timeStep>0)timeStep-=0.05;
	break;
case 't':
	demoType=(demoType++)%6;
	break;
default:
	break;
}
glutPostRedisplay();
}

//Keyboard controls with Camera2 Enabled
void KeyboardCallBackCamera2(unsigned char key, int A, int B)
{
switch(key)
{
//Camera 2
case 'a':
	moveLeft();break;// go left on the circle
case 'd':
	moveRight();break; // go right on the circle
case 's':
	cameraY-=0.1;
	moveUp(-0.1);break; // move up
case 'w':
	cameraY+=0.1;
	moveUp(0.1);break; // move down
case 'q':
	zoom(-0.1);break; //zoom in
case 'e':
	zoom(0.1);break; //zoom out
case '#':
	cameraType=cameraType%3+1;
	break; // change the camera type
case '+':
	demoAngle+=5;
	if(timeStep<1)timeStep+=0.05;
	break;
case '-':
	demoAngle-=5;
	if(timeStep>0)timeStep-=0.05;
	break;
case 't':
	demoType=(demoType++)%6;
	break;
case 27: 
	exit(0); // Terminates the program
	break;
}
glutPostRedisplay();
}

//Keyboard controls with Camera3 Enabled
void KeyboardCallBackCamera3(unsigned char key, int A, int B)
{
switch(key)
{
//Camera 3
case 's' :    //look down
	angleY -= 0.03;
	orientMeY(angleX,angleY);break;
case 'w' :   //look  up
	angleY +=0.03;
	orientMeY(angleX,angleY);break;
case 'a' : 
	angleX -= 0.03;  //look left
	orientMeX(angleX,angleY);break;
case 'd' :
	angleX += 0.03; //look right
	orientMeX(angleX,angleY);break;
case 'q':    //move forward
	moveMeFlat(1);break;
case 'e':    //move backward
	moveMeFlat(-1);break;
case '#':
	cameraType=cameraType%3+1;
	break;
case '+':
	demoAngle+=5;
	if(timeStep<1)timeStep+=0.05;
	break;
case '-':
	if(timeStep>0)timeStep-=0.05;
	demoAngle-=5;
	break;
case 't':
	demoType=(demoType++)%6;
	break;
// Escapes from the program by pressing 'Esc'
case 27: 
	exit(0); // Terminates the program
	break;
default:
break;
}
	glutPostRedisplay();
}


void initialiseOpenGL(int argc, char** argv) 
{
	glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
	glutInitWindowSize (800, 600);
	glutInitWindowPosition (200, 200);
    glutCreateWindow ("301CR Math Library ");
	init();
	glutReshapeFunc(reshape);
  	glutDisplayFunc(draw);
	glutKeyboardFunc(KeyboardCallBackCamera1);
	glutIdleFunc(idle);
}

void main(int argc, char** argv)
{
	initialiseOpenGL(argc, argv);

	renderScene();
}